import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;

public class PacketCaptureThread extends Thread {

	private DatagramSocket socket = null;
	private int bufferSize = 0;
	private AudioFormat format = null;
	private int packetCounter = 0;
	private SourceDataLine sourceLine = null;
	private InetAddress[] membershipList = null;
	private ByteArrayOutputStream[] source = null;

	public PacketCaptureThread(DatagramSocket socket, AudioFormat format,
			int datagramBufferSize, InetAddress[] membershipList) {
		super("PacketCaptureThread");
		this.socket = socket;
		this.bufferSize = datagramBufferSize;
		this.format = format;
		this.membershipList = membershipList;

		this.source = new ByteArrayOutputStream[membershipList.length];
		for (int i = 0; i < source.length; i++) {
			source[i] = new ByteArrayOutputStream(512);
		}

	}

	@Override
	public void run() {

		while (packetCounter <= 20) {
			try {
				byte[] buffer = new byte[bufferSize];
				DatagramPacket packet = new DatagramPacket(buffer,
						buffer.length);
				socket.receive(packet);

				// puts received packet to the corresponding sourceLine and
				// plays
				InetAddress senderAddress = packet.getAddress();
				for (int i = 0; i < membershipList.length; i++) {
					if (senderAddress.equals(membershipList[i])) {
						source[i].write(buffer, 0, bufferSize);
						break;
					}
				}

				// Now send this packet to everyone on the membershipList
				// EXCLUDING the person that sent it to you
				for (int i = 0; i < membershipList.length; i++) {
					// If it's NOT the person who sent us the packet, forward it
					// to membershipList
					if (!senderAddress.equals(membershipList[i])) {
						DatagramSocket forwardingSocket = new DatagramSocket();
						DatagramPacket forwardedPacket = new DatagramPacket(
								buffer, buffer.length, membershipList[i], 55556);
						forwardingSocket.send(forwardedPacket);
						forwardingSocket.close();
					}
				}

				System.out.println("Recived packet " + packetCounter
						+ " datagram packets.");
				packetCounter++;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		playThread p;
		for(int i=0; i<source.length; i++){
			p = new playThread(source[i]);
			p.start();
		}
		
		while (true) {
			try {
				byte[] buffer = new byte[bufferSize];
				DatagramPacket packet = new DatagramPacket(buffer,
						buffer.length);
				socket.receive(packet);

				// puts received packet to the corresponding sourceLine and
				// plays
				InetAddress senderAddress = packet.getAddress();
				for (int i = 0; i < membershipList.length; i++) {
					if (senderAddress.equals(membershipList[i])) {
						source[i].write(buffer, 0, bufferSize);
						break;
					}
				}

				// Now send this packet to everyone on the membershipList
				// EXCLUDING the person that sent it to you
				for (int i = 0; i < membershipList.length; i++) {
					// If it's NOT the person who sent us the packet, forward it
					// to membershipList
					if (!senderAddress.equals(membershipList[i])) {
						DatagramSocket forwardingSocket = new DatagramSocket();
						DatagramPacket forwardedPacket = new DatagramPacket(
								buffer, buffer.length, membershipList[i], 55556);
						forwardingSocket.send(forwardedPacket);
						forwardingSocket.close();
					}
				}

				System.out.println("Recived packet " + packetCounter
						+ " datagram packets.");
				packetCounter++;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	class playThread extends Thread{
		private ByteArrayOutputStream audioSource;

		public playThread(ByteArrayOutputStream baos) {
			this.audioSource = baos;
		}

		public void run() {
			try {
				while (true) {
					playBack(audioSource);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	private void playBack(ByteArrayOutputStream baos) throws IOException {

		DataLine.Info sourceInfo;
		try {
			sourceInfo = new DataLine.Info(SourceDataLine.class, format);
			sourceLine = (SourceDataLine) AudioSystem.getLine(sourceInfo);
			sourceLine.open(format);
		} catch (LineUnavailableException e) {
			e.printStackTrace();
		}

		byte buffer[] = baos.toByteArray();
		baos.reset();

		AudioInputStream ais = new AudioInputStream(new ByteArrayInputStream(
				buffer), format, buffer.length / format.getFrameSize());

		sourceLine.start();

		int count;
		while ((count = ais.read(buffer, 0, buffer.length)) != -1) {
			if (count > 0) {
				sourceLine.write(buffer, 0, count);
			}
		}
		sourceLine.drain();
		sourceLine.close();
	}

}
